; void roberts_asm (unsigned char *src, unsigned char *dst, int h, int w, int row_size)

global roberts_asm

%define width [ebp - 4]
%define rowsize [ebp - 8]

roberts_asm:
    push ebp
    mov ebp, esp
    sub esp, 8                	    ; 12 bytes para local vars
    push ebx
    push edi
    push esi                	    ; stackframe

    mov esi, [ebp + 8]              ; esi = src
    mov edi, [ebp + 12]             ; edi = dst
    mov ecx, [ebp + 16]             ; ecx = heigh
    mov ebx, [ebp + 20]             ; ebx = width
    mov eax, [ebp + 24]		    ; eax = rowsize

    mov dword width, ebx            ; local width
    mov dword rowsize, eax	    ; local rowsize
    pxor xmm7, xmm7                 ; registro para extender      
  
ciclo_h:
    cmp ecx, 1                      ; no se puede procesar la ultima fila
    je fin
    mov ebx, width                  ; cantidad de pixeles a procesar

ciclo_w:
    cmp ebx, 0                      ; si termine con la fila, voy al ciclo de h
    je fin_fila
   
    cmp ebx, 16                     ; si me quedan menos de 16 bytes por procesar en la fila,
    jbe retroceder                  ; retrocedo para obtener los ultimos 16 y asi procesarlos sin acceder a memoria q no deberia

sigo_w:                                
    movdqu xmm0, [esi]		    ; calculo derivada en x
    movdqa xmm3, xmm0
    punpcklbw xmm0, xmm7
    punpckhbw xmm3, xmm7
    
    xor eax, eax
    mov dword eax, rowsize	    ; eax = rowsize     
    
    movdqu xmm1, [esi + eax + 1]     
    movdqa xmm4, xmm1
    punpcklbw xmm1, xmm7
    punpckhbw xmm4, xmm7

    psubsw xmm0,xmm1
    psubsw xmm3,xmm4		     ; tengo en xmm0 y xmm3 los resultados de la derivada en x
                                    
    movdqu xmm1, [esi + 1]           ; calculo derivada en y
    movdqa xmm4, xmm1
    punpcklbw xmm1, xmm7  
    punpckhbw xmm4, xmm7
    
    movdqu xmm2, [esi + eax]        
    movdqa xmm5, xmm2
    punpcklbw xmm2, xmm7	    
    punpckhbw xmm5, xmm7	    
    
    psubsw xmm1, xmm2       
    psubsw xmm4, xmm5              ; tengo en xmm1 y xmm4 los resultados de la derivada en y

    pabsw xmm4,xmm4
    pabsw xmm1,xmm1
    pabsw xmm0,xmm0
    pabsw xmm3,xmm3
    
    paddusw xmm0, xmm1
    paddusw xmm3, xmm4		    ; sumo


    packuswb xmm0, xmm3		    ; pack
            
    movdqu [edi], xmm0		    ; escribo los 16 bytes en dst

    add esi, 16
    add edi, 16
    sub ebx, 16
  
jmp ciclo_w

retroceder:                       
    xor eax, eax
    mov dword eax, 16           
    sub eax, ebx                   ; (ebx < 16) -> (16 - ebx > 0)
    sub esi, eax                   ; corro el puntero para atras
    sub edi, eax
    mov dword ebx, 16
jmp sigo_w

fin_fila:
    dec ecx
jmp ciclo_h
  
fin:
    pop esi                        ; desarmo el stack frame
    pop edi          
    pop ebx
    add esp, 8
    pop ebp

    ret
